﻿using System;
using System.Data;
using System.Diagnostics;
using System.Web;

using Eneta.Portal.Common;

using Microsoft.SharePoint;

namespace Eneta.Portal.Companies
{
    internal class WebApplicationWrapper
    {
        internal static DataTable IoTable
        {
            get
            {
                Logger.LogInfo("get_IoTable: Start", "WebApplicationWrapper");
                if (WebApplication == null)
                    throw new Exception("WebApplication is null!");
                

                //if (WebApplication["IoTable"] == null)
                //{
                Logger.LogInfo("get_IoTable: IoTable is null, getting tables", "WebApplicationWrapper");
                    GetTables();
                //}
                DataTable tableCopy;

                Logger.LogInfo("get_IoTable: Copying table", "WebApplicationWrapper");
                lock (WebApplication["IoTable"])
                {
                    var table = ((DataTable) WebApplication["IoTable"]);
                    Logger.LogInfo("get_IoTable: Table has " + table.Rows.Count + " rida", "WebApplicationWrapper");
                    tableCopy = table.Copy();
                }
                Logger.LogInfo("get_IoTable: Copy has " + tableCopy.Rows.Count + " rida", "WebApplicationWrapper");
                Logger.LogInfo("get_IoTable: Finish", "WebApplicationWrapper");
                return tableCopy;
            }
            set
            {
                lock (WebApplication["IoTable"])
                {
                    WebApplication["IoTable"] = value;
                }
            }
        }

        internal static DataTable IoRelationsTable
        {
            get
            {
                Logger.LogInfo("get_IoRelationsTable: Start", "WebApplicationWrapper");
                if (WebApplication == null)
                    throw new Exception("WebApplication is null!");

                //if (WebApplication["IoRelationsTable"] == null)
                //{
                    GetTables();
                //}
                DataTable tableCopy;

                lock (WebApplication["IoRelationsTable"])
                {
                    var table = ((DataTable) WebApplication["IoRelationsTable"]);
                    Logger.LogInfo("get_IoRelationsTable: Table has " + table.Rows.Count + " rida", "WebApplicationWrapper");
                    tableCopy = table.Copy();
                }
                Logger.LogInfo("get_IoRelations: Copy has " + tableCopy.Rows.Count + " rida", "WebApplicationWrapper");
                Logger.LogInfo("get_IoRelations: Finish", "WebApplicationWrapper");
                return tableCopy;
            }
            set
            {
                lock (WebApplication["IoRelationsTable"])
                {
                    WebApplication["IoRelationsTable"] = value;
                }
            }
        }

        internal static DataTable CompaniesIoTable
        {
            get
            {
                var table = new DataTable();
                Logger.LogInfo("get_CompaniesIoTable: Start", "WebApplicationWrapper");

                var siteId = SPContext.Current.Site.ID;
                var sec = new SPSecurity.CodeToRunElevated(delegate
                    {
                        using (var site = new SPSite(siteId))
                        using (var web = site.OpenWeb("/firmad/"))
                        {
                            var list = web.Lists["Lehed"];
                            var queryString =
                                "<Where><Eq><FieldRef Name='_ModerationStatus' /><Value Type='ModStat'>Kinnitatud</Value></Eq></Where>";
                            var query = new SPQuery();
                            query.Query = queryString;

                            var items = list.GetItems(query);
                            //var items = list.Items;

                            //foreach (SPField field in list.Fields)
                            //    Logger.LogInfo("Field: " + field.InternalName, "WebApplicationWrapper");
                            table = items.GetDataTable();
                            Logger.LogInfo("Accepted companies: " + items.Count,"WebApplicationWrapper");
                        }
                    });
                SPSecurity.RunWithElevatedPrivileges(sec);

                Logger.LogInfo("get_CompaniesIoTable: Table has " + table.Rows.Count + " rows", "WebApplicationWrapper");
                Logger.LogInfo("get_CompaniesIoTable: Finish", "WebApplicationWrapper");
                return table;
            }
        }

        internal static DataTable ResultsAllTable
        {
            get
            {
                if (HttpContext.Current.Items["ResultsAllTable"] != null)
                    return (DataTable)HttpContext.Current.Items["ResultsAllTable"];

                CreateResultsTables();
                return (DataTable)HttpContext.Current.Items["ResultsAllTable"];
            }
        }

        internal static DataTable ResultsFilteredTable
        {
            get
            {
                if (HttpContext.Current.Items["ResultsFilteredTable"] != null)
                    return (DataTable)HttpContext.Current.Items["ResultsFilteredTable"];

                CreateResultsTables();
                return (DataTable)HttpContext.Current.Items["ResultsFilteredTable"];
            }
        }

        private static void CreateResultsTables()
        {
            var ioTable = IoTable;
            var ioRelationsTable = IoRelationsTable;
            var ioCompanyTable = CompaniesIoTable;
            var dto = CompanyQueryManager.GetDtoFromRequest(HttpContext.Current.Request);

            var data = CompanyQueryManager.GetQueryResults(ioTable, ioCompanyTable, ioRelationsTable, dto);
            HttpContext.Current.Items["ResultsAllTable"] = data.AllResults;
            HttpContext.Current.Items["ResultsFilteredTable"] = data.FilteredResults;
        }

        private static void GetTables()
        {
            var siteId = SPContext.Current.Site.ID;
            var webId = SPContext.Current.Web.ID;

            var sec = new SPSecurity.CodeToRunElevated(delegate
                {
                    using (var site = new SPSite(siteId))
                    {
                        using (var web = site.OpenWeb(webId))
                        {
                            WebApplication["IoTable"] = CreateIoTable(web);
                            WebApplication["IoRelationsTable"] = CreateIoRelationsTable(web);
                        }
                    }
                });
            SPSecurity.RunWithElevatedPrivileges(sec);
        }

        private static void AddIoRow(DataTable table, IoDto dto)
        {
            var dr = table.NewRow();
            dr["Level1ID"] = dto.Level1ID;
            dr["Level1Title"] = dto.Level1Title;
            dr["Level2ID"] = dto.Level2ID;
            dr["Level2Title"] = dto.Level2Title;
            dr["Level3ID"] = dto.Level3ID;
            dr["Level3Title"] = dto.Level3Title;
            dr["ProductID"] = dto.ProductID;
            dr["ProductTitle"] = dto.ProductTitle;
            table.Rows.Add(dr);
        }

        private static SPListItemCollection GetListItems(SPWeb web, string listName, string fieldName, string value)
        {
            var list = web.Lists[listName];
            var field = list.Fields[fieldName];
            var attrs = string.Empty;

            var queryString = "<Where><Eq><FieldRef Name=\"{0}\" {1} /><Value Type=\"{2}\">{3}</Value></Eq></Where>";

            if (field.FieldValueType == typeof(SPFieldLookupValue) || field.FieldValueType == typeof(SPFieldLookupValueCollection))
                attrs = "LookupId=\"True\"";

            queryString = string.Format(queryString, fieldName, attrs, field.TypeAsString, value);

            var query = new SPQuery();
            query.Query = queryString;

            return list.GetItems(query);
        }

        private static HttpApplicationState WebApplication
        {
            get
            {
                if (HttpContext.Current == null)
                    return null;

                return HttpContext.Current.Application;
            }
        }

        private static DataTable CreateIoTable(SPWeb web)
        {

            var ioTable = new DataTable();
            ioTable.Columns.Add("Level1ID", typeof(int));
            ioTable.Columns.Add("Level1Title", typeof(string));
            ioTable.Columns.Add("Level2ID", typeof(int));
            ioTable.Columns.Add("Level2Title", typeof(string));
            ioTable.Columns.Add("Level3ID", typeof(int));
            ioTable.Columns.Add("Level3Title", typeof(string));
            ioTable.Columns.Add("ProductID", typeof(int));
            ioTable.Columns.Add("ProductTitle", typeof(string));

            var level1List = web.Lists["IOLevel1"];
            foreach (SPListItem level1Item in level1List.Items)
            {
                var level2Items = GetListItems(web, "IOLevel2", "Level1", level1Item.ID.ToString());
                

                foreach (SPListItem level2Item in level2Items)
                {
                    var level3Items = GetListItems(web, "IOTopic", "Level2", level2Item.ID.ToString());

                    foreach (SPListItem level3Item in level3Items)
                    {
                        var dto = new IoDto
                                      {
                                          Level1ID = level1Item.ID,
                                          Level1Title = level1Item.Title,
                                          Level2ID = level2Item.ID,
                                          Level2Title = level2Item.Title,
                                          Level3ID = level3Item.ID,
                                          Level3Title = level3Item.Title,
                                          ProductID = 0,
                                          ProductTitle = string.Empty
                                      };

                        if(level3Item["IOProducts"] != null)
                        {
                            var productsValues = new SPFieldLookupValueCollection(level3Item["IOProducts"].ToString());
                            if (productsValues.Count > 0)
                                foreach (var productValue in productsValues)
                                {
                                    Logger.LogInfo("CreateIoTable(): Adding product: " + productValue.LookupValue, "WebApplicationWrapper");
                                    dto.ProductID = productValue.LookupId;
                                    dto.ProductTitle = productValue.LookupValue;
                                    AddIoRow(ioTable, dto);
                                }
                            else
                            {
                                Logger.LogInfo("CreateIoTable() level3.IOProducts.Count==0", "WebApplicationWrapper");
                                AddIoRow(ioTable, dto);
                            }
                        }
                        else
                        {
                            Logger.LogInfo("CreateIoTable() level3.IOProducts==null", "WebApplicationWrapper");
                            AddIoRow(ioTable, dto);
                        }
                    }
                }
            }
            Logger.LogInfo("CreateIoTable(): Found rows: " + ioTable.Rows.Count, "WebApplicationWrapper");
            return ioTable;
        }

        private static DataTable CreateIoRelationsTable(SPWeb web)
        {
            var table = new DataTable();
            table.Columns.Add("CompanyID", typeof(int));
            table.Columns.Add("IOTopicID", typeof(int));

            var list = web.Lists["IOCompany"];

            foreach (SPListItem item in list.Items)
            {
                var topicValues = (SPFieldLookupValueCollection)item.Fields["IOTopic"].GetFieldValue(item["IOTopic"].ToString());
                if (topicValues == null)
                {
                    Debug.Print("IOCompany.TopicValues on null");
                    continue;
                }

                var companyValue = (SPFieldLookupValue)item.Fields["Company"].GetFieldValue(item["Company"].ToString());
                if (companyValue == null)
                {
                    Debug.Print("IOCompany.CompanyValue on null");
                    continue;
                }
                foreach (var topicValue in topicValues)
                {
                    var row = table.NewRow();
                    row["CompanyID"] = companyValue.LookupId;
                    row["IOTopicID"] = topicValue.LookupId;
                    table.Rows.Add(row);
                }
            }
            Logger.LogInfo("CreateIoRelationsTable(): Found rows: " + table.Rows.Count, "WebApplicationWrapper");
            return table;
        }

    }
}
